package com.rpa.server.servicerpaserver.crawler.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rpa.secure.servicerpasecure.common.exception.RpaRegisterException;
import com.rpa.server.servicerpaserver.crawler.entity.Active;
import com.rpa.server.servicerpaserver.crawler.entity.CeekSetting;
import com.rpa.server.servicerpaserver.crawler.entity.Clazz;
import com.rpa.server.servicerpaserver.crawler.entity.Score;
import com.rpa.server.servicerpaserver.crawler.service.ActiveService;
import com.rpa.server.servicerpaserver.crawler.service.CeekSettingService;
import com.rpa.server.servicerpaserver.crawler.service.ClazzService;
import com.rpa.server.servicerpaserver.crawler.service.ScoreService;
import com.rpa.server.servicerpaserver.crawler.mapper.ScoreMapper;
import com.rpa.server.servicerpaserver.expose.dto.ActiveDto;
import com.rpa.server.servicerpaserver.expose.dto.ScoreDto;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 */
@Service
public class ScoreServiceImpl extends ServiceImpl<ScoreMapper, Score>
        implements ScoreService {
    @Autowired
    private ActiveService activeService;
    @Autowired
    private CeekSettingService ceekSettingService;
    @Autowired
    private ClazzService clazzService;

    @Override
    public boolean resetScore(ScoreDto scoreDto) {
        ActiveDto activeDto = new ActiveDto();
        BeanUtils.copyProperties(scoreDto, activeDto);
        List<Map<String, Object>> activeList = activeService.getActiveList(activeDto);
        if (Objects.equals("1", scoreDto.getResetType())) {
            for (Map<String, Object> score : activeList) {
                LambdaUpdateWrapper<Score> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(Score::getId, MapUtil.getStr(score, "scoreId", ""))
                        .set(Score::getScoreNumber, 100);
                this.update(updateWrapper);
            }
            return true;
        }
        if (Objects.equals("2", scoreDto.getResetType())) {
            LambdaQueryWrapper<CeekSetting> ceekSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
            buildCeekSettingWrapper(BeanUtil.beanToMap(scoreDto), ceekSettingLambdaQueryWrapper);
            CeekSetting ceekSetting = ceekSettingService.getOne(ceekSettingLambdaQueryWrapper);
            if (Objects.isNull(ceekSetting)) {
                throw new RpaRegisterException("未查询到成绩设置信息,请初始化成绩设置");
            }
            for (Map<String, Object> score : activeList) {
                int scoreNumber = countScore(score, ceekSetting);
                LambdaUpdateWrapper<Score> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(Score::getId, MapUtil.getStr(score, "scoreId", ""))
                        .set(Score::getScoreNumber, scoreNumber);
                this.update(updateWrapper);
            }
            return true;
        }
        return false;
    }

    public void buildCeekSettingWrapper(Map map, LambdaQueryWrapper<CeekSetting> queryWrapper) {
        if (Objects.nonNull(map.get("accountId"))) {
            queryWrapper.eq(CeekSetting::getAccountId, map.get("accountId"));
        }
        if (Objects.nonNull(map.get("courseId"))) {
            queryWrapper.eq(CeekSetting::getCourseId, map.get("courseId"));
        }
        if (Objects.nonNull(map.get("clazzId"))) {
            queryWrapper.eq(CeekSetting::getClazzId, map.get("clazzId"));
        }
    }

    public int countScore(Map<String, Object> score, CeekSetting ceekSetting) {
        String unsignedNumber = MapUtil.getStr(score, "unsignedNumber", "0");
        String late = MapUtil.getStr(score, "late", "0");
        String early = MapUtil.getStr(score, "early", "0");
        Integer beLate = ceekSetting.getBeLate();
        Integer leaveEarly = ceekSetting.getLeaveEarly();
        Integer absenceFromDuty = ceekSetting.getAbsenceFromDuty();
        return 100 - (Integer.parseInt(unsignedNumber) * absenceFromDuty +
                Integer.parseInt(late) * beLate +
                Integer.parseInt(early) * leaveEarly);
    }

    @Override
    public boolean updateScore(Score score) {
        LambdaUpdateWrapper<Score> set = new LambdaUpdateWrapper<Score>()
                .eq(Score::getAccountId, score.getAccountId())
                .eq(Score::getCourseId, score.getCourseId())
                .eq(Score::getClazzId, score.getClazzId())
                .eq(Score::getUserName, score.getUserName())
                .eq(Score::getScoreType, score.getScoreType())
                .set(Score::getScoreNumber, score.getScoreNumber());
        return this.update(set);
    }

    @Override
    public boolean saveScoreDefault(ScoreDto scoreDto) {
        LambdaQueryWrapper<Clazz> eq = new LambdaQueryWrapper<Clazz>()
                .eq(Clazz::getAccountId, scoreDto.getAccountId())
                .eq(Clazz::getCourseId, scoreDto.getCourseId())
                .eq(Clazz::getClazzId, scoreDto.getClazzId());
        List<Clazz> list = clazzService.list(eq);
        boolean b = true;
        if (CollUtil.isNotEmpty(list)) {
            for (Clazz clazz : list) {
                Score score = Score.builder()
                        .accountId(clazz.getAccountId())
                        .courseId(clazz.getCourseId())
                        .clazzId(clazz.getClazzId())
                        .scoreType(Integer.parseInt(scoreDto.getScoreType()))
                        .isStart(0)
                        .userName(clazz.getUserName())
                        .studentNumber(clazz.getStudentNumber())
                        .build();
                if (existsScore(score.getAccountId(), score.getCourseId(), score.getClazzId(), score.getUserName(), score.getScoreType())) {
                    LambdaUpdateWrapper<Score> set = new LambdaUpdateWrapper<Score>()
                            .eq(Score::getAccountId, score.getAccountId())
                            .eq(Score::getCourseId, score.getCourseId())
                            .eq(Score::getClazzId, score.getClazzId())
                            .eq(Score::getUserName, score.getUserName())
                            .eq(Score::getScoreType, score.getScoreType())
                            .set(Score::getIsStart, 0)
                            .set(Score::getScoreNumber, 0);
                    b= this.update(set)&&b;
                }else{
                    b=this.save(score)&&b;
                }

            }
            return b;
        }
        return false;
    }

    @Override
    public List<Map<String, Object>> getScoreTotal(ScoreDto scoreDto) {
        LambdaQueryWrapper<Score> eq = new LambdaQueryWrapper<Score>()
                .eq(Score::getAccountId, scoreDto.getAccountId())
                .eq(Score::getCourseId, scoreDto.getCourseId())
                .eq(Score::getClazzId, scoreDto.getClazzId());
        if (StrUtil.isNotEmpty(scoreDto.getUserNameOrStuNameLike())){
            eq.and(q -> q.like(Score::getUserName, scoreDto.getUserNameOrStuNameLike())
                    .or().like(Score::getStudentNumber, scoreDto.getUserNameOrStuNameLike()));
        }
        List<Map<String, Object>> scoreTotal = baseMapper.getScoreTotal(eq);
        List<Map<String, Object>> filteredScoreTotal = scoreTotal.stream()
                .filter(map -> map.values().stream().anyMatch(Objects::nonNull))
                .collect(Collectors.toList());
        return filteredScoreTotal;
    }

    @Override
    public List<List<String>> head() {
        List<List<String>> list = Arrays.asList(
                Collections.singletonList("姓名"),
                Collections.singletonList("学号"),
                Collections.singletonList("成绩"));
        return list;
    }

    @Override
    public List<List<Object>> dataList(ScoreDto scoreDto) {
        List<List<Object>> list = new ArrayList<>();
        List<Score> scoreList = this.getScoreList(scoreDto);
        for (Score score : scoreList){
            List<Object> row = new ArrayList<>();
            row.add(StringUtils.defaultIfBlank(score.getUserName(), "-"));
            row.add(StringUtils.defaultIfBlank(score.getStudentNumber(), "-"));
            row.add(StringUtils.defaultIfBlank(String.valueOf(score.getScoreNumber()), "-"));
            list.add(row);
        }
        return list;
    }

    @Override
    public List<List<String>> headTotal(List<Map<String, Object>> filteredScoreTotal) {
        if (filteredScoreTotal == null || filteredScoreTotal.isEmpty()) {
            return head(); // 如果没有数据，返回基础表头
        }

        //  使用 Set  来存储唯一的  scoreName
        Set<String> scoreNames = new LinkedHashSet<>(); //  使用 LinkedHashSet 保证顺序

        // 提取所有的 scoreName (确保去重和排序)
        for (Map<String, Object> row : filteredScoreTotal) {
            if (row != null) {
                if (row.get("scoreName1") != null && StringUtils.isNotBlank(row.get("scoreName1").toString())) {
                    scoreNames.add(row.get("scoreName1").toString());
                }
                if (row.get("scoreName2") != null && StringUtils.isNotBlank(row.get("scoreName2").toString())) {
                    scoreNames.add(row.get("scoreName2").toString());
                }
                if (row.get("scoreName3") != null && StringUtils.isNotBlank(row.get("scoreName3").toString())) {
                    scoreNames.add(row.get("scoreName3").toString());
                }
                if (row.get("scoreName4") != null && StringUtils.isNotBlank(row.get("scoreName4").toString())) {
                    scoreNames.add(row.get("scoreName4").toString());
                }
            }
        }

        // 构建动态表头
        List<List<String>> head = new ArrayList<>();
        head.add(Collections.singletonList("姓名"));
        head.add(Collections.singletonList("学号"));

        for (String scoreName : scoreNames) {
            head.add(Collections.singletonList(scoreName));  // 使用 scoreName  作为表头
        }
        head.add(Collections.singletonList("总分")); // 添加 "总分"

        return head;
    }

    @Override
    public List<List<Object>> dataListTotal(List<Map<String, Object>> filteredScoreTotal) {
        List<List<Object>> dataList = new ArrayList<>();
        for (Map<String, Object> row : filteredScoreTotal) {
            List<Object> rowData = new ArrayList<>();
            rowData.add(StringUtils.defaultIfBlank(row.get("userName").toString(), "-"));
            rowData.add(StringUtils.defaultIfBlank(row.get("studentNumber").toString(), "-"));
            if (row.get("score1") != null && StringUtils.isNotBlank(row.get("score1").toString())) {
                rowData.add(new BigDecimal(row.get("score1").toString()).setScale(2, RoundingMode.HALF_UP).toString());
            }
            if (row.get("score2") != null && StringUtils.isNotBlank(row.get("score2").toString())) {
                rowData.add(new BigDecimal(row.get("score2").toString()).setScale(2, RoundingMode.HALF_UP).toString());
            }
            if (row.get("score3") != null && StringUtils.isNotBlank(row.get("score3").toString())) {
                rowData.add(new BigDecimal(row.get("score3").toString()).setScale(2, RoundingMode.HALF_UP).toString());
            }
            if (row.get("score4") != null && StringUtils.isNotBlank(row.get("score4").toString())) {
                rowData.add(new BigDecimal(row.get("score4").toString()).setScale(2, RoundingMode.HALF_UP).toString());
            }
            rowData.add(StringUtils.defaultIfBlank(new BigDecimal(row.get("totalScore").toString()).setScale(2, RoundingMode.HALF_UP).toString(), "-"));
            dataList.add(rowData);
        }
        return dataList;
    }

    @Override
    public List<Score> getScoreList(ScoreDto scoreDto) {
        LambdaUpdateWrapper<Score> eq = new LambdaUpdateWrapper<Score>()
                .eq(Score::getAccountId, scoreDto.getAccountId())
                .eq(Score::getCourseId, scoreDto.getCourseId())
                .eq(Score::getClazzId, scoreDto.getClazzId())
                .eq(Score::getScoreType, scoreDto.getScoreType());
        if (StrUtil.isNotBlank(scoreDto.getUserNameOrStuNameLike())) {
            eq.and(i -> i.like(Score::getUserName, scoreDto.getUserNameOrStuNameLike())
                    .or()
                    .like(Score::getStudentNumber, scoreDto.getUserNameOrStuNameLike()));
        }
        List<Score> scoreList = this.list(eq);
        return scoreList;
    }

    private boolean existsScore(String accountId, String courseId, String clazzId, String userName, Integer scoreType) {
        LambdaQueryWrapper<Score> scoreLambdaQueryWrapper = new LambdaQueryWrapper<Score>()
                .eq(Score::getAccountId, accountId)
                .eq(Score::getCourseId, courseId)
                .eq(Score::getClazzId, clazzId)
                .eq(Score::getUserName, userName)
                .eq(Score::getScoreType, scoreType);
        return this.exists(scoreLambdaQueryWrapper);
    }

}




